package br.com.poliwar {
	import br.com.network.Conexao;
	import br.com.network.DataVO;
	import br.com.network.events.ConexaoEvent;
	import br.com.poliwar.model.IObserver;
	import br.com.poliwar.model.Mensagens;
	import br.com.poliwar.model.StateGUI;
	import br.com.poliwar.model.vo.LoginVO;
	import br.com.poliwar.model.vo.UsuarioVO;
	import br.com.poliwar.view.events.TelaBuscaSalaEvent;
	import br.com.poliwar.view.events.TelaCadastroEvent;
	import br.com.poliwar.view.events.TelaConectarEvent;
	import br.com.poliwar.view.events.TelaLoginEvent;
	import br.com.poliwar.view.events.TelaMenuEvent;
	import br.com.poliwar.view.events.TelaSelecionaCorEvent;
	import br.com.poliwar.view.TelaBuscaSala;
	import br.com.poliwar.view.TelaCadastro;
	import br.com.poliwar.view.TelaConectar;
	import br.com.poliwar.view.TelaLogin;
	import br.com.poliwar.view.TelaMenu;
	import br.com.poliwar.view.TelaSelecionaCor;
	import br.com.poliwar.view.Topo;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import org.utils.statemachine.events.StateMachineEvent;
	import org.utils.statemachine.State;
	import org.utils.statemachine.StateMachine;
	/**
	 * ...
	 * @author Ricardo Teixeira
	 */
	public class JogoCliente extends Sprite implements IObserver {
		
		private var sala:Sala;
		
		private var objetivo:Objetivo;
		private var tabuleiro:Tabuleiro;
		private var stateMachineGUI:StateMachine;
		
		private var topo:Topo;
		private var conteinerTela:Sprite;
		private var telaAtual:MovieClip;
		private var conexao:Conexao;
		private var usuario:UsuarioVO;
		
		public function JogoCliente () {
			
			/*this.tabuleiro = new Tabuleiro ();			
			this.sala = new Sala ();
			this.objetivo = new Objetivo ();*/
			
			this.conteinerTela = new Sprite ();
			
			this.topo = new Topo ();
			
			this.addChild (topo);
			this.addChild (this.conteinerTela);
			
			this.inicializarStateGUI ();
			
			this.conexao = Conexao.instance;
			this.conexao.addEventListener (ConexaoEvent.CONECTADO, onServerConectado)
			this.conexao.addEventListener (ConexaoEvent.CONEXAO_FECHADA, onServerDesconectado)
			this.conexao.addEventListener (ConexaoEvent.RECEBE_DADO, onServerData)
			this.conexao.attach (this);
		}
		
		private function inicializarStateGUI ():void {			
			var stateConectar:State = new State (StateGUI.CONECTAR, "*", onEnterConectar, onExit);
			var stateLogin:State = new State (StateGUI.LOGIN, [StateGUI.CONECTAR, StateGUI.MENU, StateGUI.CADASTRO], onEnterLogin, onExit);
			var stateCadastro:State = new State (StateGUI.CADASTRO, [StateGUI.LOGIN], onEnterCadastro, onExit);
			var stateMenu:State = new State (StateGUI.MENU, [StateGUI.LOGIN,StateGUI.BUSCA,StateGUI.SELECIONAR_COR, StateGUI.ESPERA, StateGUI.JOGO], onEnterMenu, onExit);
			var stateBusca:State = new State (StateGUI.BUSCA, [StateGUI.MENU, StateGUI.SELECIONAR_COR], onEnterBusca, onExit);
			var stateSelCor:State = new State (StateGUI.SELECIONAR_COR, [StateGUI.BUSCA, StateGUI.MENU], onEnterSelecionaCor, onExit);
			var stateEspera:State = new State (StateGUI.ESPERA, [StateGUI.SELECIONAR_COR, StateGUI.JOGO], onEnterEspera, onExit);
			var stateJogo:State = new State (StateGUI.JOGO, [StateGUI.MENU], onEnterJogo, onExit);
			
			this.stateMachineGUI = new StateMachine ();
			this.stateMachineGUI.addEventListener (StateMachineEvent.TRANSITION_COMPLETE, onTransitionComplete);
			this.stateMachineGUI.addEventListener (StateMachineEvent.TRANSITION_DENIED, onTransitionDenied);
			this.stateMachineGUI.addState (stateConectar.name, stateConectar);
			this.stateMachineGUI.addState (stateMenu.name, stateMenu);
			this.stateMachineGUI.addState (stateBusca.name, stateBusca);
			this.stateMachineGUI.addState (stateSelCor.name, stateSelCor);
			this.stateMachineGUI.addState (stateEspera.name, stateEspera);
			this.stateMachineGUI.addState (stateLogin.name, stateLogin);
			this.stateMachineGUI.addState (stateCadastro.name, stateCadastro);
			this.stateMachineGUI.addState (stateJogo.name, stateJogo);
			this.stateMachineGUI.initialState = StateGUI.CONECTAR;
		}
		
		private function onTransitionDenied(e:StateMachineEvent):void {
			trace ("onTransitionDenied current:", e.currentState);
			trace ("onTransitionDenied from:", e.fromState);
			trace ("onTransitionDenied to:", e.toState);
		}
		
		private function onTransitionComplete(e:StateMachineEvent):void {
			trace ("onTransitionComplete current:", e.currentState);
			trace ("onTransitionComplete from:", e.fromState);
			trace ("onTransitionComplete to:", e.toState);
		}
		
		private function onServerData(e:ConexaoEvent):void {
			var obj:Object = Object (e.dado);
			var dataVO:DataVO;
			var dataType:String;
			var data:Object;
			
			for (var prop:String in obj) {
				if (prop == "dataType") {
					dataType = obj[prop];
				} else {
					data = obj[prop];
				}				
			}
			dataVO = new DataVO (dataType, data);
			
			trace ("onServerData", dataType);
			
			switch (dataVO.dataType) {
				case Mensagens.LOGIN:
					this.usuario = new UsuarioVO (dataVO.data.id, dataVO.data.nome, dataVO.data.email, dataVO.data.senha);
					this.stateMachineGUI.changeState (StateGUI.MENU);
					break;
				case Mensagens.USUARIO_NAO_EXISTE:
					trace ("UsuarioNaoExiste");
					break;
				case Mensagens.CADASTRAR:
					this.stateMachineGUI.changeState (StateGUI.LOGIN);
					trace ("Cadastrado");
					break;
				case Mensagens.CRIAR_JOGO:
					var usuarios:Vector.<UsuarioVO> = new Vector.<UsuarioVO> ();
					
					for (var i:int = 0; i < dataVO.data.usuarios.length; i++) {
						var o:Object = dataVO.data.usuarios[i];
						usuarios.push ( new UsuarioVO ( o.id, o.nome, o.email, o.senha) );
					}
					var moderador:UsuarioVO = new UsuarioVO (dataVO.data.moderador.id, dataVO.data.moderador.nome, dataVO.data.moderador.email, dataVO.data.moderador.senha);
					this.sala = new Sala (dataVO.data.id, moderador , usuarios, dataVO.data.quantidade);
					this.stateMachineGUI.changeState (StateGUI.SELECIONAR_COR);
					break;
			}
		}
		
		private function onServerDesconectado(e:ConexaoEvent):void {
			
		}
		
		private function onServerConectado(e:ConexaoEvent):void {
			this.stateMachineGUI.changeState (StateGUI.LOGIN);
		}
		
		private function onEnterConectar(e:StateMachineEvent):void{
			var tela:TelaConectar = new TelaConectar ();
			tela.addEventListener (TelaConectarEvent.CONECTAR, onConectarCliente);
			this.conteinerTela.addChild (tela);
			trace ("onEnterConectar");
			this.telaAtual = tela;
		}
		
		private function onConectarCliente(e:TelaConectarEvent):void {
			this.conexao.conectar (e.host);
		}
		
		private function onEnterLogin(e:StateMachineEvent):void{
			var tela:TelaLogin = new TelaLogin ();
			tela.addEventListener (TelaLoginEvent.DADOS_INVALIDOS, onLoginInvalido);
			tela.addEventListener (TelaLoginEvent.ENTRAR, onLoginEntrar);
			tela.addEventListener (TelaLoginEvent.NOVO, onLoginNovo);
			this.conteinerTela.addChild (tela);
			
			this.telaAtual = tela;
		}
		
		private function onLoginEntrar(e:TelaLoginEvent):void {			
			this.conexao.enviar (e.loginVO, Mensagens.LOGIN);
		}
		
		private function onLoginNovo(e:TelaLoginEvent):void {
			this.stateMachineGUI.changeState (StateGUI.CADASTRO);
		}
		
		private function onLoginInvalido(e:TelaLoginEvent):void {
			trace ("#erro [JogoCliente]: Login - Dados Inválidos");
		}
		
		private function onEnterCadastro(e:StateMachineEvent):void{
			var tela:TelaCadastro = new TelaCadastro ();
			tela.addEventListener (TelaCadastroEvent.CADASTRAR, onCadastrar);
			tela.addEventListener (TelaCadastroEvent.CADASTRO_INVALIDO, onCadastroInvalido);
			this.conteinerTela.addChild (tela);
			
			this.telaAtual = tela;
		}
		
		private function onCadastrar(e:TelaCadastroEvent):void {
			// TODO Cadastrar no banco de dados.
			trace ("Cadastrado com sucesso");
			this.conexao.enviar (e.usuarioVO, Mensagens.CADASTRAR);
			//this.stateMachineGUI.changeState (StateGUI.LOGIN);
		}
		
		private function onCadastroInvalido(e:TelaCadastroEvent):void {
			trace ("#erro [JogoCliente]: Cadastro - Dados Inválidos");
		}
		
		private function onEnterMenu(e:StateMachineEvent):void{
			var tela:TelaMenu = new TelaMenu ();
			tela.addEventListener (TelaMenuEvent.BUSCAR_JOGO, onMenuBuscarJogo);
			tela.addEventListener (TelaMenuEvent.CRIAR_JOGO, onMenuCriarJogo);
			tela.addEventListener (TelaMenuEvent.AJUDA, onMenuAjuda);
			tela.addEventListener (TelaMenuEvent.SAIR, onMenuSair);
			this.conteinerTela.addChild (tela);
			
			this.telaAtual = tela;
		}
		
		private function onMenuSair(e:TelaMenuEvent):void {
			// TODO Implementar sair do jogo
			trace ("SAIR");
		}
		
		private function onMenuAjuda(e:TelaMenuEvent):void {
			// TODO Implementar tela de ajuda
			trace ("AJUDA");
		}
		
		private function onMenuBuscarJogo(e:TelaMenuEvent):void {
			this.stateMachineGUI.changeState (StateGUI.BUSCA);
		}
		
		private function onEnterBusca(e:StateMachineEvent):void{
			var tela:TelaBuscaSala = new TelaBuscaSala ();
			tela.addEventListener (TelaBuscaSalaEvent.SELECIONA_SALA, onBuscaSalaSeleciona);
			tela.addEventListener (TelaBuscaSalaEvent.VOLTAR, onBuscaSalaVoltar);
			this.conteinerTela.addChild (tela);
			
			this.telaAtual = tela;
		}
		
		private function onBuscaSalaVoltar(e:TelaBuscaSalaEvent):void {
			this.sala = null;
			this.stateMachineGUI.changeState (StateGUI.MENU);
		}
		
		private function onBuscaSalaSeleciona(e:TelaBuscaSalaEvent):void {
			this.sala = e.sala;
			this.stateMachineGUI.changeState (StateGUI.SELECIONAR_COR);
		}
		
		private function onMenuCriarJogo(e:TelaMenuEvent):void {
			this.conexao.enviar (this.usuario, Mensagens.CRIAR_JOGO);
		}
		
		private function onEnterJogo(e:StateMachineEvent):void{
			
		}
		
		private function onEnterEspera(e:StateMachineEvent):void{
			
		}
		
		private function onEnterSelecionaCor(e:StateMachineEvent):void{
			var tela:TelaSelecionaCor = new TelaSelecionaCor (this.usuario.nome);
			tela.addEventListener (TelaSelecionaCorEvent.SELECIONA, onSelecionaCor);
			this.conteinerTela.addChild (tela);
			
			this.telaAtual = tela;
		}
		
		private function onSelecionaCor(e:TelaSelecionaCorEvent):void {
			trace ("Cadastrado com sucesso");
			this.conexao.enviar ( { idSala: -1, idCor: e.cor, nomeUsuario: this.usuario.nome }, Mensagens.SELECIONAR_COR);
		}
		
		private function onExit(e:StateMachineEvent):void{
			this.conteinerTela.removeChild (this.telaAtual);
		}
		
		public function update():void{
			// TODO Implementar o update da inteface IObserver.
		}
		
	}

}